package cn.edu.cug.cs.gtl.docsrv.shp.querier;

import cn.edu.cug.cs.gtl.docsrv.shp.block.ShapeBlock;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geojson.geom.GeometryJSON;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class DefaultGeometryQuerier implements GeometryQuerier{
    ShapeBlock block;

    public DefaultGeometryQuerier(ShapeBlock block){
        this.block=block;
    }

    @Override
    public List<Feature> disjoint(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.disjoint(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> touches(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.touches(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> intersects(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.intersects(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> crosses(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.crosses(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> within(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.within(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> contains(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.contains(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> overlaps(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.overlaps(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> covers(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.covers(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> coveredBy(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.coveredBy(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<Feature> equals(Geometry g) {
        List<Feature> fl = new ArrayList<>();
        Geometry t = null;
        for(SimpleFeature sf : this.block.getFeatures()){
            t = (Geometry)(sf.getDefaultGeometry());
            if(g.equals(t))
                fl.add(sf);
        }
        return fl;
    }

    @Override
    public List<SimpleFeature> getFeatures(){
        return this.block.getFeatures();
    }

    @Override
    public List<Geometry> getGeometries() {
        return this.block.getFeatures().stream().map(i->(Geometry)(i.getDefaultGeometry())).collect(Collectors.toList());
    }

    @Override
    public List<String> getGeometryJSONs() {
        List<String>  ls = new ArrayList<>();
        List<Geometry> lg = getGeometries();
        GeometryJSON json = new GeometryJSON();

        for(Geometry g: lg){
            ls.add(json.toString(g));
        }
        return ls;
    }

    @Override
    public List<String> getFeatureJSONs() {

        List<String>  ls = new ArrayList<>();
        try {
            FeatureJSON featureJSON = new FeatureJSON();

            List<SimpleFeature> lg = getFeatures();

            for(SimpleFeature g: lg){
                if(g.getFeatureType()!=null) {
                    featureJSON.setFeatureType(g.getFeatureType());
                }
                String s = featureJSON.toString(g);
                System.out.println(s);
                ls.add(s);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }

        return ls;
    }

    @Override
    public Envelope getEnvelope() {

        List<Geometry> lg = getGeometries();
        Envelope e = new Envelope();
        for(Geometry g: lg){
            e.expandToInclude(g.getEnvelopeInternal());
        }
        return e;
    }
}
